package com.zmn.oms.services.impl.redistribute;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.zmn.anole.dubbo.interfaces.AnoleEncryptUtils;
import com.zmn.anole.dubbo.interfaces.AnoleRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.common.dio.redistribute.OrderWorkRedistributeApplyQuery;
import com.zmn.oms.model.entity.redistribute.OrderWorkRedistributeApply;
import com.zmn.oms.persistence.interfaces.redistribute.OrderWorkRedistributeApplyDao;
import com.zmn.oms.services.interfaces.redistribute.OrderWorkRedistributeApplyService;
import io.shardingsphere.api.HintManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderWorkRedistributeApplyServiceImpl implements OrderWorkRedistributeApplyService {

    @Resource
    OrderWorkRedistributeApplyDao orderWorkRedistributeApplyDao;
    @Reference(version = com.zmn.anole.dubbo.interfaces.AnoleRemoteService.VERSION, check = false)
    private AnoleRemoteService anoleRemoteService;

    @Override
    public OrderWorkRedistributeApply selectByPrimaryKey(Long id) {
        OrderWorkRedistributeApply apply = orderWorkRedistributeApplyDao.selectByPrimaryKey(id);
        return decryptAddress(apply);
    }

    @Override
    public List<OrderWorkRedistributeApply> listByQuery(OrderWorkRedistributeApplyQuery query) {
        List<OrderWorkRedistributeApply> applyList = orderWorkRedistributeApplyDao.listByQuery(query);
        this.batchDecryptAddress(applyList);
        return applyList;
    }

    @Override
    public List<OrderWorkRedistributeApply> listByOrderIdListAndRedistributeStatus(List<Long> orderIdList, Integer redistributeStatus) {
        return orderWorkRedistributeApplyDao.listByOrderIdListAndRedistributeStatus(orderIdList, redistributeStatus);
    }

    @Override
    public List<OrderWorkRedistributeApply> listApplyForEngineerManager(OrderWorkRedistributeApplyQuery query) {
        return orderWorkRedistributeApplyDao.listApplyForEngineerManager(query);
    }

    @Override
    public int countByQuery(OrderWorkRedistributeApplyQuery query) {
        return orderWorkRedistributeApplyDao.countByQuery(query);
    }

    @Override
    public int countByQueryForEngineerManager(OrderWorkRedistributeApplyQuery query) {
        return orderWorkRedistributeApplyDao.countByQueryForEngineerManager(query);
    }

    @Override
    public int delete(Long id) {
        return orderWorkRedistributeApplyDao.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(OrderWorkRedistributeApply record) {
        OrderWorkRedistributeApply apply = BeanMapper.map(record, OrderWorkRedistributeApply.class);
        this.encryptAddress(apply);
        int count = orderWorkRedistributeApplyDao.insertSelective(apply);
        record.setRedistributeId(apply.getRedistributeId());
        return count;
    }

    @Override
    public int updateByPrimaryKeySelective(OrderWorkRedistributeApply record) {
        OrderWorkRedistributeApply apply = BeanMapper.map(record, OrderWorkRedistributeApply.class);
        this.encryptAddress(apply);
        return orderWorkRedistributeApplyDao.updateByPrimaryKeySelective(apply);
    }

    @Override
    public OrderWorkRedistributeApply selectByOrderIdAndWorkIdAndRedistributeStatus(Long orderId, Long workId, Integer code) {
        OrderWorkRedistributeApply apply = orderWorkRedistributeApplyDao.selectByOrderIdAndWorkIdAndRedistributeStatus(orderId, workId, code);
        return decryptAddress(apply);
    }

    @Override
    public OrderWorkRedistributeApply selectByOrderIdAndWorkIdAndRedistributeStatusSrcMaster(Long orderId, Long workId, Integer redistributeStatus) {
        try (HintManager hintManager = HintManager.getInstance()) {
            hintManager.setMasterRouteOnly();
            OrderWorkRedistributeApply apply = orderWorkRedistributeApplyDao.selectByOrderIdAndWorkIdAndRedistributeStatus(orderId, workId, redistributeStatus);
            return decryptAddress(apply);
        }
    }

    @Override
    public OrderWorkRedistributeApply selectByKeySrcMaster(Long redistributeId) {
        try (HintManager hintManager = HintManager.getInstance()) {
            hintManager.setMasterRouteOnly();
            OrderWorkRedistributeApply apply = orderWorkRedistributeApplyDao.selectByPrimaryKey(redistributeId);
            return decryptAddress(apply);
        }
    }

    /**
     * 加密地址信息
     * @param apply
     */
    private void encryptAddress(OrderWorkRedistributeApply apply) {
        if (Objects.isNull(apply)) {
            return;
        }
        if (StringUtil.isNotBlank(apply.getAddress())) {
            ResponseDTO<String> responseDTO = anoleRemoteService.encrypt(apply.getAddress());
            log.debug("anoleRemoteService#encrypt addr 入参：{}，出参：{}", apply.getAddress(), JSON.toJSONString(responseDTO));
            if (responseDTO.isSuccess()) {
                apply.setAddress(responseDTO.getData());
            }
        }
    }

    /**
     * 解密地址信息
     * @param apply
     */
    private OrderWorkRedistributeApply decryptAddress(OrderWorkRedistributeApply apply) {
        if (Objects.isNull(apply)) {
            return apply;
        }
        if (StringUtil.isNotBlank(apply.getAddress())) {
            ResponseDTO<String> responseDTO = anoleRemoteService.decrypt(apply.getAddress());
            log.debug("anoleRemoteService#decrypt addr 入参：{}，出参：{}", apply.getAddress(), JSON.toJSONString(responseDTO));
            if (responseDTO.isSuccess()) {
                apply.setAddress(responseDTO.getData());

            }
        }
        return apply;
    }

    /**
     * 批量解密地址信息
     * @param applyList
     */
    private void batchDecryptAddress(List<OrderWorkRedistributeApply> applyList) {
        if (CollectionUtil.isNullOrEmpty(applyList)) {
            return;
        }
        // 得到地址明文
        Map<String, String> addrPlainText = Maps.newHashMap();
        Map<String, String> addrMaps = applyList.stream()
                .filter(e -> StringUtils.isNotBlank(e.getAddress()))
                .collect(Collectors.toMap(e -> String.valueOf(e.getRedistributeId()), OrderWorkRedistributeApply::getAddress));
        ResponseDTO<Map<String, String>> addrMapsRemote = AnoleEncryptUtils.getInstance(anoleRemoteService).batchDecryptMap(addrMaps);
        if (addrMapsRemote.isSuccess()) {
            addrPlainText = addrMapsRemote.getData();
        }

        // 赋值明文
        for (OrderWorkRedistributeApply apply : applyList) {
            String addr = addrPlainText.get(String.valueOf(apply.getRedistributeId()));
            if (Objects.nonNull(addr)) {
                apply.setAddress(addr);
            }
        }

    }
}